//
//  UIButton+ClickCount.m
//  RuntimeDemo
//
//  Created by zxs on 2021/2/25.
//

#import "UIButton+ClickCount.h"
#import <objc/runtime.h>
#import <objc/message.h>

// 关联对象的key
static NSString *clickCountKey = @"clickCount";
static NSString *currentActionBlockKey = @"currentActionBlock";

@implementation UIButton (ClickCount)

+ (void)load {
    // 方法替换；用自定义的点击响应替换系统的点击响应
    // 只能交换一次
    static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            SEL origilaSEL = @selector(addTarget: action: forControlEvents:);
            
            SEL hook_SEL = @selector(xw_addTarget: action: forControlEvents:);
            
            //交换方法
            Method origilalMethod = class_getInstanceMethod(self, origilaSEL);
            
            
            Method hook_method = class_getInstanceMethod(self, hook_SEL);
            
            
            class_addMethod(self,
                            origilaSEL,
                            class_getMethodImplementation(self, origilaSEL),
                            method_getTypeEncoding(origilalMethod));
            
            class_addMethod(self,
                            hook_SEL,
                            class_getMethodImplementation(self, hook_SEL),
                            method_getTypeEncoding(hook_method));
            
            method_exchangeImplementations(class_getInstanceMethod(self, origilaSEL), class_getInstanceMethod(self, hook_SEL));
            
        });
}

// 替换的方法，
- (void)xw_addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents {
    
    __weak typeof(target) weakTarget = target;
    __weak typeof(self) weakSelf = self;

    if (action) {
        self.currentActionBlock = ^{
            @try {
                ((void (*)(void *, SEL,  typeof(weakSelf) ))objc_msgSend)((__bridge void *)(weakTarget), action , weakSelf);
            } @catch (NSException *exception) {
            } @finally {
            }
        };
    }
    
    //发送消息 其实是本身  要执行的action 先执行，写下来的 xw_clicked:方法
    [self xw_addTarget:self action:@selector(xw_clicked:) forControlEvents:controlEvents];
}

//拦截了按钮点击后要执行的代码
- (void)xw_clicked:(UIButton *)sender{
    //统计 在这个方法中执行想要操作的
    self.clickCount++;
    
    NSLog(@"%@ 点击 %ld次 ",[sender titleForState:UIControlStateNormal], self.clickCount);
    
    //执行原来要执行的方法
    sender.currentActionBlock();
}

// setter/getter
// 点击次数
- (void)setClickCount:(NSInteger)clickCount {
    objc_setAssociatedObject(self, &clickCountKey, @(clickCount), OBJC_ASSOCIATION_ASSIGN);
}

- (NSInteger)clickCount {
    NSNumber *clickCountValue = objc_getAssociatedObject(self, &clickCountKey);
    return clickCountValue.integerValue;
}

// 点击响应
- (void)setCurrentActionBlock:(void (^)(void))currentActionBlock {
    objc_setAssociatedObject(self, &currentActionBlockKey, currentActionBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (void (^)(void))currentActionBlock {
    return objc_getAssociatedObject(self, &currentActionBlockKey);
}

@end
